package com.select.course.service.impl;

import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.select.course.entity.*;
import com.select.course.listener.StudentListener;
import com.select.course.mapper.UserStudentMapper;
import com.select.course.service.*;
import com.select.course.utils.JwtUtil;
import com.select.course.utils.MsgConstant;
import com.select.course.utils.PageUtils;
import com.select.course.utils.R;
import com.select.course.vo.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.lang.Nullable;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author 24820
 * @description 针对表【c_user_student】的数据库操作Service实现
 * @createDate 2022-10-26 10:21:42
 */
@Service
public class UserStudentServiceImpl extends ServiceImpl<UserStudentMapper, UserStudent>
        implements UserStudentService {
    @Resource
    @Lazy
    private AdminService adminService;
    @Autowired
    private SysUserRoleService sysUserRoleService;
    @Resource
    private SchoolCollegeService schoolCollegeService;
    @Resource
    private SchoolMajorService schoolMajorService;
    @Resource
    private SchoolClassService schoolClassService;
    @Resource
    private StudentCourseRelationService studentCourseRelationService;
    @Resource
    private SchoolCourseService schoolCourseService;
    @Resource
    private CourseRoomService courseRoomService;
    @Resource
    private CourseRoomRelationService courseRoomRelationService;
    @Resource
    private TeacherCourseRelationService teacherCourseRelationService;
    @Resource
    private UserTeacherService userTeacherService;
    @Autowired
    private AuthenticationManager authenticationManager;

    @Override
    public R login(StudentVo studentVo) {
//        UserStudent id_number = this.getOne(new QueryWrapper<UserStudent>().eq("id_number", studentVo.getUserId()));
        UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken =
                new UsernamePasswordAuthenticationToken(studentVo.getUserId(), studentVo.getPassword());
        Authentication authenticate = authenticationManager.authenticate(usernamePasswordAuthenticationToken);

        if (Objects.isNull(authenticate)) {
            throw new RuntimeException("登陆失败！");
        }
        LoginUser loginUser = (LoginUser) authenticate.getPrincipal();
        if (!loginUser.getPermissions().get(0).toString().equals("ROLE_student")) {
            throw new RuntimeException("账号错误！");
        }
        String jwt = JwtUtil.createJWT(loginUser.getUser().getIdNumber());
        Map<String, Object> map = new HashMap<>();
        map.put("authentication", jwt);
        map.put("username", loginUser.getUser().getUserName());
        return R.ok(map);
    }

    @Transactional
    @Override
    public R deleteStudent(String userId) {
        UserStudent userStudent = this.getOne(new QueryWrapper<UserStudent>().eq("id_number", userId));

        if (!StringUtils.isEmpty(userStudent)) {
            boolean b = this.remove(new QueryWrapper<UserStudent>().eq("id_number", userId));
            if (b) {
                return R.ok();
            }
            return R.error(111, "删除学生信息失败");
        }

        return R.error(111, "用户ID重复！");

    }

    @Transactional(readOnly = true)
    @Override
    public StudentVo getStuByIdNumber(String idNumber) {
        UserStudent userStudent = this.getOne(new QueryWrapper<UserStudent>().eq("id_number", idNumber));
        StudentVo studentVo = this.packageStudentVo(userStudent);


        return studentVo;
    }

    @Transactional
    @Override
    public void updateStudent(StudentVo studentVo) {
//        UserStudent userStudent = this.packageStudent(studentVo);
        UserStudent student = new UserStudent();
        student.setStudentName(studentVo.getStudentName());
        student.setEmail(studentVo.getEmail());
        student.setSex(studentVo.getSex());
        if (studentVo.getPassword() != null) {
            BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
            String encode = bCryptPasswordEncoder.encode(studentVo.getPassword());
            student.setPassword(encode);
        }
        this.update(student, new QueryWrapper<UserStudent>().eq("id_number", studentVo.getUserId()));
    }

    @Override
    public PageUtils getStudentList(PageVo pageVo) {
        Page<UserStudent> objectPage = new Page<UserStudent>(pageVo.getPageNum(), pageVo.getPageSize());
        String collegeName = pageVo.getCollege();
        QueryWrapper<UserStudent> userStudentQueryWrapper = new QueryWrapper<>();

        if (!StringUtils.isEmpty(collegeName)) {
            SchoolCollege college = schoolCollegeService.getOne(new QueryWrapper<SchoolCollege>().eq("name", collegeName));
            userStudentQueryWrapper.eq("college_id",college.getId());
        }
        String select_major = pageVo.getMajor();
        if (!StringUtils.isEmpty(select_major)) {
            SchoolMajor major = schoolMajorService.getOne(new QueryWrapper<SchoolMajor>().eq("name", select_major));
            userStudentQueryWrapper.eq("major_id",major.getId());
        }
        String className = pageVo.getClassName();
        if (!StringUtils.isEmpty(className))  {
            SchoolClass schoolClass = schoolClassService.getOne(new QueryWrapper<SchoolClass>().eq("name", className));
            userStudentQueryWrapper.eq("class_id",schoolClass.getId());
        }
        String sex = pageVo.getSex();
        if(!StringUtils.isEmpty(sex)) {
            userStudentQueryWrapper.eq("sex", sex);
        }
        String queryInfo = pageVo.getQuery();
        if (!StringUtils.isEmpty(queryInfo)) {
            userStudentQueryWrapper.and(wrapper -> {
                wrapper.like("student_name", queryInfo).or().like("id_number", queryInfo);
            });
        }
        Page<UserStudent> page = this.page(objectPage, userStudentQueryWrapper);
        List<UserStudent> records = page.getRecords();
        List<StudentVo> collect = records.stream().map(e -> {
            StudentVo studentVo = this.packageStudentVo(e);
            return studentVo;
        }).collect(Collectors.toList());
        PageUtils pageUtils = new PageUtils(page);
        pageUtils.setList(collect);
        return pageUtils;
    }

    @Transactional
    @Override
    public void selectCourse(String courseId, String userId) {
        SchoolCourse schoolCourse = schoolCourseService.getOne(new QueryWrapper<SchoolCourse>().eq("course_id", courseId));
        schoolCourse.setCourseCount(schoolCourse.getCourseCount()-1);
        schoolCourseService.updateById(schoolCourse);
        UserStudent student = this.getOne(new QueryWrapper<UserStudent>().eq("id_number", userId));
        StudentCourseRelation studentCourseRelation = new StudentCourseRelation();
        studentCourseRelation.setStudentId(student.getIdNumber());
        studentCourseRelation.setCourseId(schoolCourse.getId());
        studentCourseRelation.setRegisterTime(new Date());
        studentCourseRelationService.save(studentCourseRelation);
    }

    @Override
    public PageUtils getSelectedCourse(CoursePageVo coursePageVo) {
        String id = coursePageVo.getUserId();
        Page<SchoolCourse> schoolCoursePage = new Page<>(coursePageVo.getPageNum(), coursePageVo.getPageSize());
        QueryWrapper<SchoolCourse> wrapper = new QueryWrapper<>();

        if (!StringUtils.isEmpty(id)) {
            String courseType = coursePageVo.getCourseType();
            if (!StringUtils.isEmpty(courseType)) {
                if (courseType.equals("选修")) {
                    wrapper.eq("course_type",0);

                }else {
                    wrapper.eq("course_type",1);

                }
            }
            Integer score = coursePageVo.getCourseCore();
            if (!StringUtils.isEmpty(score)) {
                wrapper.eq("course_core",score);
            }
            String query = coursePageVo.getQuery();
            if (!StringUtils.isEmpty(query)) {
                wrapper.and(e -> {
                    e.like("course_id", query).or().like("name", query);
                });
            }
            UserStudent student = this.getOne(new QueryWrapper<UserStudent>().eq("id_number", id));
            List<StudentCourseRelation> courseRelationList = studentCourseRelationService.list(new QueryWrapper<StudentCourseRelation>().eq("student_id", student.getIdNumber()));
            if (courseRelationList.size() == 0 || courseRelationList == null) {
                return null;
            }
            List<Long> collect = courseRelationList.stream().map(e -> {
                Long courseId = e.getCourseId();
                return courseId;
            }).collect(Collectors.toList());
            wrapper.in("id",collect);
            Page<SchoolCourse> page = schoolCourseService.page(schoolCoursePage, wrapper);
            List<SchoolCourse> records = page.getRecords();
            List<CourseVo> collect1 = records.stream().map(e -> {
                CourseVo courseVo = new CourseVo();
                BeanUtils.copyProperties(e, courseVo);
                CourseVo courseVo1 = this.packageCourseVo(e, courseVo);
                return courseVo1;
            }).collect(Collectors.toList());
            PageUtils pageUtils = new PageUtils(page);
            pageUtils.setList(collect1);
            return pageUtils;
        }
        return null;
    }

    @Override
    public List<CourseVo> getKeChengBiao(String userId) {
//        UserStudent student = this.getOne(new QueryWrapper<UserStudent>().eq("id_number", userId));
        List<StudentCourseRelation> studentCourseRelationList = studentCourseRelationService.list(new QueryWrapper<StudentCourseRelation>().
                eq("student_id", userId));
        List<CourseVo> courseVoList = studentCourseRelationList.stream().map(e -> {
            CourseVo courseVo = new CourseVo();
            SchoolCourse schoolCourse = schoolCourseService.getById(e.getCourseId());
            this.packageCourseVo(schoolCourse, courseVo);
            return courseVo;
        }).collect(Collectors.toList());
        return courseVoList;
    }

    @Transactional
    @Override
    public void deleteCourse(String courseId, String userId) {
        SchoolCourse course_id = schoolCourseService.getOne(new QueryWrapper<SchoolCourse>().eq("course_id", courseId));
        course_id.setCourseCount(course_id.getCourseCount() + 1);
        schoolCourseService.updateById(course_id);
        boolean b = studentCourseRelationService.remove(new QueryWrapper<StudentCourseRelation>().
                eq("course_id", course_id.getId()).eq("student_id", userId));
        if (!b) {
            throw new RuntimeException();
        }
    }

    @Override
    public R addStudent(StudentVo studentVo) {
        long idNumber = this.count(new QueryWrapper<UserStudent>().eq("id_number", studentVo.getUserId()));
        long count2 = userTeacherService.count(new QueryWrapper<UserTeacher>().eq("id_number", studentVo.getUserId()));
        if (idNumber <= 0 || count2 <= 0) {
            UserStudent userStudent = this.packageStudent(studentVo);
            BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
            String encode = bCryptPasswordEncoder.encode(studentVo.getUserId());
            userStudent.setPassword(encode);
            userStudent.setRegisterTime(new Date());
            this.save(userStudent);
            boolean save = sysUserRoleService.save(new SysUserRole(userStudent.getIdNumber(), "3"));
        }
        return R.error(MsgConstant.UserEnum.USER_DUPLICATE.getCode(), MsgConstant.UserEnum.USER_DUPLICATE.getMsg());

    }

    @Override
    public CourseVo packageCourseVo(SchoolCourse schoolCourse, CourseVo courseVo) {
        BeanUtils.copyProperties(schoolCourse, courseVo);
        CourseRoomRelation course_id = courseRoomRelationService.getOne(new QueryWrapper<CourseRoomRelation>().eq("course_id", schoolCourse.getId()));
        if (!StringUtils.isEmpty(course_id)) {
            courseVo.setWeekTime(schoolCourse.getWeekTime());
            courseVo.setClassTime(schoolCourse.getClassTime());
            String s = "每" + schoolCourse.getWeekTime() + "第" + schoolCourse.getClassTime() + "节";
            courseVo.setCTime(s);
        } else {
            courseVo.setWeekTime("暂未分配");
            courseVo.setClassTime("暂未分配");
            String s = "暂未分配";
            courseVo.setCTime(s);
        }

        CourseRoomRelation courseRoomRelation = courseRoomRelationService.getOne(new QueryWrapper<CourseRoomRelation>().eq("course_id", schoolCourse.getId()));
        if (!StringUtils.isEmpty(courseRoomRelation)) {
            CourseRoom courseRoom = courseRoomService.getOne(new QueryWrapper<CourseRoom>().eq("id", courseRoomRelation.getRoomId()));
            String roomName = courseRoom.getRoomName();
            courseVo.setClassRoom(roomName);
        } else {
            courseVo.setClassRoom("暂未分配");
        }

        TeacherCourseRelation teacherCourseRelationServiceById = teacherCourseRelationService.getOne(new QueryWrapper<TeacherCourseRelation>().eq("course_id", schoolCourse.getId()));
        if (!StringUtils.isEmpty(teacherCourseRelationServiceById)) {
            UserTeacher id = userTeacherService.getOne(new QueryWrapper<UserTeacher>().eq("id", teacherCourseRelationServiceById.getTeacherId()));
            courseVo.setTeacher(id.getTeacherName());
        } else {
            courseVo.setTeacher("暂未分配");
        }
        courseVo.setStartWeek("第" + schoolCourse.getStartWeek() + "周");
        courseVo.setEndWeek("第" + schoolCourse.getEndWeek() + "周");

        if (schoolCourse.getCourseType() == 1) {
            courseVo.setCourseType("必修");
        } else {
            courseVo.setCourseType("选修");
        }
        return courseVo;
    }

    @Override
    public SumarizeVo getXueFenBiao(String userId) {
        SumarizeVo sumarizeVo = new SumarizeVo();
//        UserStudent id_number = this.getOne(new QueryWrapper<UserStudent>().eq("id_number", userId));
        List<StudentCourseRelation> studentCourseRelationList = studentCourseRelationService.list(new QueryWrapper<StudentCourseRelation>().eq("student_id", userId));
        List<HashMap<String, String>> hashMapList = studentCourseRelationList.stream().map(e -> {
            HashMap<String, String> hashMap = new HashMap<>();
            SchoolCourse schoolCourse = schoolCourseService.getOne(new QueryWrapper<SchoolCourse>().eq("id", e.getCourseId()));
            if (schoolCourse.getCourseType() == 1) {
                hashMap.put("kechengname", schoolCourse.getName());
                hashMap.put("xuefen", String.valueOf(schoolCourse.getCourseCore()));
            }
            return hashMap;
        }).filter(e -> {
            if (e.isEmpty()) {
                return false;
            } else {
                return true;
            }
        }).collect(Collectors.toList());
        sumarizeVo.setChartValue(hashMapList);

        return sumarizeVo;
    }

    @Override
    public SumarizeVo getXueFenXuna(String userId) {
        SumarizeVo sumarizeVo = new SumarizeVo();
//        UserStudent id_number = this.getOne(new QueryWrapper<UserStudent>().eq("id_number", userId));
        List<StudentCourseRelation> studentCourseRelationList = studentCourseRelationService.list(new QueryWrapper<StudentCourseRelation>().eq("student_id", userId));
        List<HashMap<String, String>> hashMapList = studentCourseRelationList.stream().map(e -> {
            HashMap<String, String> hashMap = new HashMap<>();
            SchoolCourse schoolCourse = schoolCourseService.getOne(new QueryWrapper<SchoolCourse>().eq("id", e.getCourseId()));
            if (schoolCourse.getCourseType() == 0) {
                hashMap.put("kechengname", schoolCourse.getName());
                hashMap.put("xuefen", String.valueOf(schoolCourse.getCourseCore()));
            }
            return hashMap;
        }).filter(e -> {
            if (e.isEmpty()) {
                return false;
            } else {
                return true;
            }
        }).collect(Collectors.toList());
        sumarizeVo.setChartValue(hashMapList);

        return sumarizeVo;
    }

    @Override
    public CourseVo getCuuri(String courseId) {
        SchoolCourse schoolCourse = schoolCourseService.getOne(new QueryWrapper<SchoolCourse>().eq("course_id", courseId));
        CourseVo courseVo = new CourseVo();
        CourseVo packageCourseVo = this.packageCourseVo(schoolCourse, courseVo);
        return packageCourseVo;
    }

    @Override
    public StudentVo getStudentSelf(String userId) {
        UserStudent userStudent = this.getOne(new QueryWrapper<UserStudent>().eq("id_number", userId));
        StudentVo studentVo = this.packageStudentVo(userStudent);
        return studentVo;
    }


    @Override
    public StudentVo packageStudentVo(UserStudent userStudent) {
        StudentVo studentVo = new StudentVo();
        studentVo.setStudentName(userStudent.getStudentName());
        studentVo.setUserId(userStudent.getIdNumber());
        studentVo.setAge(userStudent.getAge());
        studentVo.setRegisterTime(userStudent.getRegisterTime());
        studentVo.setEmail(userStudent.getEmail());
        studentVo.setSex(userStudent.getSex());
//        studentVo.setPassword(userStudent.getPassword());
        Map<String, String> stringStringMap = this.packageCollegeAndMajor(userStudent.getCollegeId(), userStudent.getMajorId(), userStudent.getClassId());
        studentVo.setCollege(stringStringMap.get("collegeName"));
        studentVo.setMajor(stringStringMap.get("majorName"));
        studentVo.setClassName(stringStringMap.get("className"));

        return studentVo;
    }

    @Override
    public UserStudent packageStudent(StudentVo studentVo) {
        UserStudent userStudent = new UserStudent();
        userStudent.setStudentName(studentVo.getStudentName());
        userStudent.setEmail(studentVo.getEmail());
        userStudent.setSex(studentVo.getSex());
        userStudent.setIdNumber(studentVo.getUserId());
        userStudent.setRegisterTime(studentVo.getRegisterTime());
        userStudent.setAge(studentVo.getAge());
//        userStudent.setPassword(studentVo.getPassword());
        Map<String, Long> stringLongMap = this.releaseCollegeAndMajor(studentVo.getCollege(), studentVo.getMajor(), studentVo.getClassName());
        userStudent.setCollegeId(stringLongMap.get("collegeId"));
        userStudent.setMajorId(stringLongMap.get("majorId"));
        userStudent.setClassId(stringLongMap.get("classId"));
        return userStudent;
    }

    @Override
    public Map<String, String> packageCollegeAndMajor(@Nullable Long collegeId, @Nullable Long majorId, @Nullable Long classId) {

        HashMap<String, String> hashMap = new HashMap<>();
        if (!StringUtils.isEmpty(collegeId)) {
            SchoolCollege name = schoolCollegeService.getById(collegeId);
            if(!StringUtils.isEmpty(name)) {
                hashMap.put("collegeName", name.getName());
            }else {
                hashMap.put("collegeName","暂无");
            }


        }
        if (!StringUtils.isEmpty(majorId)) {
            SchoolMajor name1 = schoolMajorService.getById(majorId);
            if(!StringUtils.isEmpty(name1)) {
                hashMap.put("majorName", name1.getName());
            }else {
                hashMap.put("majorName","暂无");
            }

        }
        if (!StringUtils.isEmpty(classId)) {
            SchoolClass byId = schoolClassService.getById(classId);
            if(!StringUtils.isEmpty(byId)) {
                hashMap.put("className", byId.getName());
            }else {
                hashMap.put("className","暂无");
            }

        }
        return hashMap;
    }

    @Override
    public Map<String, Long> releaseCollegeAndMajor(@Nullable String collegeName, @Nullable String majorName, @Nullable String className) {
        HashMap<String, Long> stringLongHashMap = new HashMap<>();
        if (!StringUtils.isEmpty(majorName)) {
            SchoolMajor name = schoolMajorService.getOne(new QueryWrapper<SchoolMajor>().eq("name", majorName));

            stringLongHashMap.put("majorId", name != null ? name.getId() : -1L);
        } else stringLongHashMap.put("majorId", -1L);
        if (!StringUtils.isEmpty(collegeName)) {
            SchoolCollege name1 = schoolCollegeService.getOne(new QueryWrapper<SchoolCollege>().eq("name", collegeName));

            stringLongHashMap.put("collegeId", name1 != null ? name1.getId() : -1L);
        } else stringLongHashMap.put("collegeId", -1L);
        if (!StringUtils.isEmpty(className)) {
            SchoolClass name2 = schoolClassService.getOne(new QueryWrapper<SchoolClass>().eq("name", className));
            stringLongHashMap.put("classId", name2 != null ? name2.getId() : -1L);
        } else stringLongHashMap.put("classId", -1L);
        return stringLongHashMap;
    }

    @Override
    public R importData(MultipartFile file) {
        try {
            StudentListener studentListener = new StudentListener(this);
            EasyExcel.read(file.getInputStream(), StudentVo.class, studentListener).sheet().doRead();
            int successCount = studentListener.getSuccessCount();
            return R.ok().put("successCount", successCount);
        } catch (IOException e) {
            e.printStackTrace();
            return R.error(111, "导入出错！请联系管理员！");
        }
    }

    @Override
    public void exportData(HttpServletResponse response) {
        try {
            response.setContentType("application/vnd.ms-excel");
            response.setCharacterEncoding("utf-8");
// 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
            String fileName = URLEncoder.encode("学生信息表", "UTF-8");
            response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
            response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");

            List<UserStudent> userStudentList = baseMapper.selectList(null);
            List<StudentVo> studentVoList = new ArrayList<>(userStudentList.size());
            for (UserStudent userStudent : userStudentList) {
                StudentVo studentVo = this.packageStudentVo(userStudent);
                studentVoList.add(studentVo);
            }
            ArrayList<String> strings = new ArrayList<>();
            strings.add("password");
            EasyExcel.write(response.getOutputStream(), StudentVo.class).excludeColumnFiledNames(strings).sheet("学生信息表").doWrite(studentVoList);
        } catch (IOException e) {
            throw new RuntimeException();
        }
    }


}




